package mx.vlabs.soapdroid;

import java.lang.reflect.Proxy;
import java.net.URL;

import javax.xml.namespace.QName;

import mx.vlabs.soapdroid.annotations.WebService;
import mx.vlabs.soapdroid.exception.WebServiceException;

public class ServiceDelegateImpl extends ServiceDelegate{
	
	private URL wsdlURL;
	private QName serviceName;
	
	public ServiceDelegateImpl(URL wsdlURL, QName serviceName, Class serviceClass)
    {      
		this.wsdlURL = wsdlURL;
		this.serviceName = serviceName;
    }
	
	public ServiceDelegateImpl(URL wsdlURL, QName serviceName, Class serviceClass, WebServiceFeature[] features)
    {      
		this.wsdlURL = wsdlURL;
		this.serviceName = serviceName;
    }
	

	@Override
	public <T> T getPort(QName qname, Class<T> seiClass) {
		// TODO Auto-generated method stub
		assertSEIConstraints(seiClass);
		
		return getPortInternal(qname, seiClass);
	}

	@Override
	public <T> T getPort(Class<T> seiClass) {
		// TODO Auto-generated method stub
		assertSEIConstraints(seiClass);
		
		WebService wsAnot = seiClass.getAnnotation(WebService.class);
		
		return getPort(new QName(wsAnot.targetNamespace(),wsAnot.name()),seiClass);
	}

	@Override
	public <T> T getPort(QName portName, Class<T> serviceEndpointInterface,
			WebServiceFeature... features) {
		// TODO Auto-generated method stub
		return getPort(portName,serviceEndpointInterface);
	}
	
	private <T> T getPortInternal(QName portName, Class<T> seiClass)
    {
	      T port = (T)createProxy(serviceName,portName,seiClass);
	      return port; 
    }

   @SuppressWarnings({ "unchecked", "rawtypes" })
   private void assertSEIConstraints(Class seiClass)
   {
      if (seiClass == null)
         throw new IllegalArgumentException("sei cannot be null");

      if (!seiClass.isAnnotationPresent(WebService.class))
         throw new WebServiceException("Webservice annotation not present");
   }

	
	@SuppressWarnings("unchecked")
	private <T> T createProxy(QName serviceName,QName portName,Class<T> seiClass) throws WebServiceException{
		
		if (seiClass == null)
	         throw new IllegalArgumentException("PortType class cannot be null");
		
		ClientProxy clientProxy = new ClientProxy(wsdlURL,serviceName,portName,seiClass);
		
		T proxy;
		
		try{
			proxy = (T) Proxy.newProxyInstance(seiClass.getClassLoader(), new Class[] {seiClass}, clientProxy);
		
		}catch(RuntimeException ex){
			throw new WebServiceException("cannot create proxy");
		}
		
		return proxy;
		
	}

}
